library(tidymodels)
library(textrecipes)
library(tokenizers)
library(tidyverse)
library(ggraph)
library(igraph)
library(tidytext)
library(syuzhet)
library(textdata)
library(ggthemes)
library(topicmodels)
library(tm)
library(stringr)
library(readr)
library(vip)1 Klassifikation von Hate Speech
1.1 Einleitung
Ziel dieses Posts ist es, Hate Speech auf Twitter zu klassifizieren. Hass im Internet ist nach wie vor ein großes gesellschaftliches Problem, weshalb es sich lohnt, genauer zu untersuchen, was diesen Hass ausmacht und wie man ihn zuverlässig und automatisiert erkennen kann. Hierfür liegt ein Datensatz vor, der eine Auswahl englischer als Hate Speech oder nicht Hate Speech markierter Tweets enthält. Die Analyse dieser Daten lässt sich in zwei Teile gliedern: Zunächst werden Methoden der explorativen Datenanalyse angewandt, um Muster und Auffälligkeiten in den Tweets zu identifizieren. Anschließend werden die gewonnenen Erkenntnisse genutzt, um sowohl Shallow-Learning- als auch Deep-Learning-Algorithmen darauf zu trainieren, Tweets korrekterweise als Hate Speech einzuordnen.
1.2 Vorbereitung
1.2.1 Pakte laden
1.2.2 Datenimport
Bei den Daten handelt es sich um eine Auswahl englischer Tweets, die bereits auf Hate Speech untersucht wurden und sich daher gut für das Training von Modellen zur Erkennung von Hassrede eignen.
d_hate <- read_csv("d_hate.csv")1.3 Explorative Datenanalyse
Ziel ist es, auf Grundlage der Tweets einige nützliche Features zu generieren, die sich als Prädiktor für die AV (Hatespeech oder nicht) eignen. Hierfür müssen zunächst einige Charakteristika von Tweets, die als Hate Speech gelten, herausgearbeitet werden. Die Methoden und der Code orientieren sich stark an dem Vorgehen, das in Julia Silges und David Robinsons Buch “Text Mining with R” (https://www.tidytextmining.com/) beschrieben wird. Für die nachfolgenden Visualisierungen wird eine mit Hilfe der Seite https://davidmathlogic.com/colorblind eigens erstellte Farbpalette verwendet, die gewährleistet, dass keine Art der Farbenblindheit die Lesbarkeit der Diagramme beeinträchtigt.
Uriah_Flint <- c("#8175AA", "#6FB899", "#3AA2C3", "#8BD4F9", "#DDCC77", "#CC6677", "#882255")1.3.1 Vorverarbeitung
Um eine sinnvolle Analyse durchzuführen, müssen noch einige Datenvorverarbeitungsschritte durchlaufen werden. Diese beinhalten die Tokenisierung, das Entfernen von Stopwords und das Bereinigen der Tweets, die Links oder ähnliche Elemente enthalten.
d_hate_clean <- d_hate %>%
mutate(tweet = str_remove_all(tweet, pattern = 'RT\\s*|http[s]?://\\S+|\\d+'))
set.seed(123)
train_test_split <- initial_split(d_hate_clean, prop = .8, strata = class)
d_train <- training(train_test_split)
d_test <- testing(train_test_split)1.3.1.1 Tokenisierung
tweets_token <- d_train %>%
unnest_tokens(word, tweet)1.3.1.2 Entfernung der Stopwords
data(stopwords_en, package = "lsa")
stopwords_en <- tibble(word = stopwords_en)
tweets_token <- tweets_token %>%
anti_join(stopwords_en)Joining with `by = join_by(word)`
1.3.1.3 Sentimentwerte
senti <- get_sentiments("afinn") %>%
mutate(neg_pos = case_when(value > 0 ~ "pos",
TRUE ~ "neg"))
tweets_senti <- tweets_token %>%
inner_join(senti)Joining with `by = join_by(word)`
1.3.2 Anteil von Hate Speech
Um sich einen ersten Überblick über die Daten zu verschaffen, ist es sinnvoll, zunächst einmal den Anteil der als Hate Speech markierten Tweets zu überprüfen.
tweets_token %>%
summarise(`Anteil Hate Speech` = mean(class == "hate speech")) %>%
round(2)class_totals <- tweets_token %>%
count(class, name = "class_total")
ggplot(class_totals, aes(x = "", y = class_total, fill = class)) +
geom_bar(stat = "identity") +
labs(title = "Anteil an Hate Speech",
x = NULL,
y = NULL,
fill = "Klasse") +
geom_text(aes(label = class_total), position = position_stack(vjust = 0.5)) +
theme_light() +
scale_fill_manual(values = Uriah_Flint)
Der Anteil der Hate Speech in diesem Datensatz beträgt 25 Prozent. Die Tweets anderer Kategorien sind also deutlich in der Mehrheit.
1.3.3 Worthäufigkeiten
Einen weiteren interessanten Einblick gewähren die Worthäufigkeiten. Durch die Visualisierung der am meisten verwendeten Wörter und Wortpaare ist es bereits möglich, einen Einblick in das Vokabular zu erhalten und dieses unter den Klassen zu vergleichen.
tweets_count_senti <- tweets_senti %>%
group_by(class) %>%
count(class, word, sort = TRUE) %>%
slice_head(n = 10)
word_counts <- left_join(tweets_count_senti, class_totals, by = "class")
# Berechnung der gewichteten Häufigkeit
word_counts <- word_counts %>%
mutate(weighted_frequency = n / class_total)
# Visualisierung der gewichteten Häufigkeiten
ggplot(word_counts, aes(x = reorder(word, weighted_frequency), y = weighted_frequency, fill = class)) +
geom_bar(stat = "identity") +
facet_wrap(~class, scales = "free_y") +
coord_flip() +
labs(title = "Gewichtete Häufigkeiten der Wörter in Abhängigkeit von der Klasse",
x = "Wort",
y = "Gewichtete Häufigkeit") +
theme_light() +
scale_fill_manual(values = Uriah_Flint)
Beim Vergleich der häufigsten Wörter fällt direkt auf, dass Beleidigungen und Schimpfwörter charakteristisch für Hate Speech sind, da die Liste der zehn häufigsten Wörter fast nur aus solchen Einträgen besteht. Das Vokabular der anderen Kategorie ist im Vergleich dazu überaus harmlos. Diese Harmlosigkeit wird durch das häufigste Wort “lol” noch auf die Spitze getrieben. Interessant ist jedoch auch, dass sich das Wort “hate” in dieser Liste wiederfindet. Hier wäre es interessant, im weiteren Verlauf der Analyse den Kontext in Erfahrung zu bringen. Auf der anderen Seite ist “hate” jedoch ein sehr gängiges Wort und dient zur Beschreibung normaler Gefühlszustände, ohne direkt Hass zu verbreiten.
tweets_bigram <-
d_train %>%
unnest_tokens(bigram, tweet, token = "ngrams", n = 2) %>%
filter(!is.na(bigram))
tweets_bigram <- tweets_bigram %>%
separate(bigram, c("word1", "word2"), sep = " ")%>%
filter(!word1 %in% stop_words$word) %>%
filter(!word2 %in% stop_words$word)
tweets_bigram %>%
unite(bigram, word1, word2, sep = " ") %>%
group_by(class) %>%
count(bigram, sort = TRUE) %>%
slice_max(n, n = 10) %>%
mutate(bigram = reorder(bigram, n)) %>%
ggplot(aes(n, bigram, fill = class) ) +
facet_wrap(~class, scales = "free_y") +
geom_col() +
labs(title = "Bigramme nach Häufigkeit",
x = "Häufigkeit",
y = "Bigramm") +
scale_fill_manual(values = Uriah_Flint) +
theme_light()
Die Analyse der häufigsten Wortpaare deckt sich mit der Analyse der häufigsten Wörter. Sie bringt insofern neue Erkenntnisse, als deutlich wird, dass sich der Hass hauptsächlich gegen ethnische und sexuelle Minderheiten richtet. Dies wird anhand von Begriffen wie “white trash” und “fucking faggot” deutlich. Bemerkenswert ist ebenfalls, dass es sich keinesfalls hauptsächlich um Hass gegen Schwarze handelt, sondern genauso auch Menschen mit heller Hautfarbe ethnisch beleidigt werden.
1.3.4 Wortbeziehungen
Im Folgenden werden alle Wortpaare, die häufiger als sechs Mal vorkommen, visualisiert. Hierdurch werden die Kontexte der Wörter deutlicher und die Beziehungen können uns Aufschluss darüber geben, in welchem Zusammenhang “hate” verwendet wird.
tweets_bigram_count <- tweets_bigram %>%
count(word1, word2, sort = TRUE)
visualize_bigrams <- function(bigrams) {
set.seed(2016)
a <- grid::arrow(type = "closed", length = unit(.15, "inches"))
bigrams %>%
graph_from_data_frame() %>%
ggraph(layout = "fr") +
geom_edge_link(aes(edge_alpha = n), show.legend = FALSE, arrow = a) +
geom_node_point(color = "#6FB899", size = 5) +
geom_node_text(aes(label = name), vjust = 1, hjust = 1) +
theme_void()
}
tweets_bigram_count %>%
filter(n > 6,
!str_detect(word1, "\\d"),
!str_detect(word2, "\\d")) %>%
visualize_bigrams()Warning: Using the `size` aesthetic in this geom was deprecated in ggplot2 3.4.0.
ℹ Please use `linewidth` in the `default_aes` field and elsewhere instead.

Zum Kontext des Wortes “hate” erhalten wir hier keine neuen Hinweise. Jedoch wird klar ersichtlich, in welchen Kombinationen Schimpfwörter verwendet werden. Außerdem werden Ambiguitäten deutlich, da Wörter wie “trash” und “colored” sowohl als rassistische Beleidigung als auch als Beschreibung von Alltagsgegenständen auftauchen.
1.3.5 Sentimentanalyse
Zweck der Sentimentanalyse ist es, herauszufinden, ob die Sentimentausprägungen die beiden Klassen klar voneinander abgrenzen.
# Zählen der negativen und positiven Sentimente
tweets_senti2 <- tweets_senti %>%
group_by(class) %>%
count(neg_pos, name = "count")
# Visualisierung der Sentimentantanteile nach Klasse
ggplot(tweets_senti2, aes(x = "", y = count, fill = neg_pos)) +
geom_bar(stat = "identity") +
labs(title = "Sentimentanteile nach Klasse",
x = NULL,
y = NULL,
fill = "Sentiment") +
facet_wrap(~ class) +
geom_text(aes(label = count), position = position_stack(vjust = 0.5)) +
theme_light() +
scale_fill_manual(values = Uriah_Flint)
In obigem Diagramm wird ersichtlich, dass hasslastige Tweets überwiegend negativ sind, während sich die Sentimente der anderen Klasse in der Waage halten. Das Sentiment ist also ein entscheidender Faktor bei der Klassifizierung von Hate Speech und sollte beim Training des Modells berücksichtigt werden.
1.3.6 Themenanalyse
Die Themenanalyse soll Aufschluss darüber geben, ob es bestimmte Themengebiete gibt, die charakteristisch für Hate Speech sind.
tweets_token_counts_hate <- tweets_token %>%
filter(class == "hate speech") %>%
count(word, sort = TRUE) %>%
filter(n > 19) %>%
select(word)
tweets_dtm_hate <- DocumentTermMatrix(tweets_token_counts_hate)
tweets_dtm_hatetweets_lda_hate <- LDA(tweets_dtm_hate, k = 4, control = list(seed = 42))
tweets_themen_hate <- tidy(tweets_lda_hate, matrix = "beta")
tweets_themen_hate <- tweets_themen_hate %>%
group_by(topic) %>%
slice_max(beta, n = 7) %>%
ungroup() %>%
arrange(topic, -beta)
tweets_themen_hate %>%
mutate(term = reorder_within(term, beta, topic)) %>%
ggplot(aes(beta, term, fill = factor(topic))) +
geom_col(show.legend = FALSE) +
facet_wrap(~ topic, scales = "free") +
scale_y_reordered() +
labs(title = "Themen von Hate Speech") +
theme_minimal() +
scale_fill_manual(values = Uriah_Flint)
Obwohl sich die Themen nicht eindeutig voneinander abgrenzen, sind dennoch schwache Muster erkennbar. Thema Eins scheint sich vor allem aus allgemeinen Obszönitäten zusammenzusetzen, während das zweite Thema aus Beleidigungen gegen Schwule und Schwarze und etwas härteren Wörtern wie “kill” und “shit” besteht. In Thema Drei und Vier treten Beleidigungen gegen Frauen sowie die LGBTQ-Community in den Vordergrund. Viel wichtiger als diese kleinen Unterschiede ist jedoch das große Bild der Themen, welches wie schon bei der Analyse der Worthäufigkeiten festgestellt, hauptsächlich aus ethnischen und sexuellen Beleidigungen und Schimpfwörtern besteht.
1.3.7 Schimpfwörter
Schimpfwörter scheinen eine große Rolle bei Hate Speech zu spielen. Deshalb erachte ich es als sinnvoll, Schimpfwörter als Feature in das spätere Rezept mit aufzunehmen. Hierzu verwende ich diese Liste, welche ich um ein paar Einträge (rassistische Beleidigungen) ergänzt habe: https://www.insult.wiki/list-of-insults.
insults <- read.csv("insults.csv")
tweets_token %>%
group_by(class) %>%
count(word, sort = TRUE) %>%
left_join(insults, by = "word") %>%
mutate(insult = case_when(is.na(value) == TRUE ~ "Nein",
TRUE ~ "Ja")) %>%
select(-value) %>%
ggplot(aes(x = "", y = n, fill = insult)) +
geom_bar(stat = "identity") +
labs(title = "Anteil der Beleidigungen nach Klasse",
x = NULL,
y = NULL,
fill = "Beleidigung") +
facet_wrap(~ class, scales = "free_y") +
theme_light() +
scale_fill_manual(values = Uriah_Flint)
Tatsächlich ist der Anteil der Beleidigungen in Hate Speech Tweets höher, jedoch fällt er deutlich geringer aus als erwartet.
1.3.8 Emojis
Die Überlegung, dass Hate Speech feindselige Emojis enthält, ist sehr plausibel. Um aggressive Emojis zu kennzeichnen, verwende ich ein von mir erstelltes Lexikon, das solche Emojis enthält und schreibe eine Funktion, die zählt, wieviele feindselige Emojis in einem Tweet vorkommen. Der Totenkopf ist nicht in der Liste der feindseligen Emojis enthalten, da dieser hauptsächlich als Synonym oder Steigerung des Lach-Emojis verwendet wird (engl.: “That’s too funny. I’m dead!”).
hostile_emojis <- read.csv("hostile_emojis.csv")count_hostile_emojis <- function(text) {
# Initialisiere einen leeren Vektor für die Zählungen
counts <- numeric(length(hostile_emojis$emoji))
# Iteriere über jedes Emoji und zähle die Übereinstimmungen im Text
for (i in seq_along(hostile_emojis$emoji)) {
counts[i] <- sum(lengths(str_extract_all(text, hostile_emojis$emoji[i])))
}
# Summiere die Gesamtanzahl der Übereinstimmungen
total_count <- sum(counts)
return(total_count)
}
dummy <- c("🗑", "bogen", "😠", "👹", "💩", "baby", "und", "🆗")
count_hostile_emojis(dummy)[1] 3
d_train %>%
mutate(hostile_emojis_n = map_int(tweet, count_hostile_emojis)) %>%
summarise(`Feindselige Emojis` = mean(hostile_emojis_n == 1))Die Vermutung, dass Hate Speech feindselige Emojis enthält, stellt sich in diesem Fall als falsch heraus. Da es keinen einzigen Emoji dieser Art gibt, wird dieser Ansatz für die Modellierung verworfen.
1.4 Modellierung
1.4.1 Shallow-Learning
In der Modellierung ist es nun das Ziel, einen Algorithmus darauf zu trainieren, möglichst präzise Hate Speech vorherzusagen. Der Algorithmus meiner Wahl ist der XGBoost. Zunächst werden jedoch noch Rezepte formuliert, die die Erkenntnisse aus der Analyse nun in nützliche Features umwandeln.
1.4.1.1 Rezepte definieren
Rezept Eins enthält Schimpfwörter, Sentimentwerte und die Themenanalyse. Außerdem werden noch die üblichen Textverarbeitungsschritte durchgeführt sowie ein Tokenfilter angewandt.
rec1 <-
recipe(class ~ ., data = d_train) %>%
step_text_normalization(tweet) %>%
step_mutate(insult = get_sentiment(tweet,
method = "custom",
lexicon = insults)) %>%
step_mutate(senti = get_sentiment(tweet)) %>%
step_tokenize(tweet, token = "words") %>%
step_tokenfilter(tweet, max_tokens = 1e2) %>%
step_stopwords(tweet, language = "en", stopword_source = "snowball") %>%
step_stem() %>%
step_lda(tweet, num_topics = 6)Rezept Zwei enthält statt der Themenanalyse die Tf-idf-Maße.
rec2 <-
recipe(class ~ ., data = d_train) %>%
update_role(id, new_role = "id") %>%
step_text_normalization(tweet) %>%
step_mutate(insult = get_sentiment(tweet,
method = "custom",
lexicon = insults)) %>%
step_mutate(senti = get_sentiment(tweet)) %>%
step_tokenize(tweet, token = "words") %>%
step_tokenfilter(tweet, max_tokens = 1e2) %>%
step_stopwords(tweet, language = "en", stopword_source = "snowball") %>%
step_stem() %>%
step_tfidf(tweet)baked <- rec1 %>%
prep() %>%
bake(new_data = NULL)
bakedbaked2 <- rec2 %>%
prep() %>%
bake(new_data = NULL)
baked21.4.1.2 Modell definieren
xgb <-
boost_tree(
mtry = tune(),
trees = tune(),
tree_depth = tune(),
learn_rate = tune(),
min_n = tune(),
loss_reduction = tune()
) %>%
set_engine("xgboost") %>%
set_mode("classification") %>%
translate()1.4.1.3 Workflowset erstellen
Das Modell wird getuned. Hierfür wird zweifache Kreuzvalidierung mit einer Wiederholung verwendet. Der geringe Performance-Zuwachs durch intensiveres Tuning mit mehr Folds und Wiederholungen würde in diesem Fall nicht die höhere Rechenzeit rechtfertigen.
preproc <- list(rec1 = rec1, rec2 = rec2)
models <- list(xgb = xgb)
all_workflows <- workflow_set(preproc, models)
model_set <-
all_workflows %>%
workflow_map(
resamples = vfold_cv(d_train,
v = 2,
repeats = 1,
strata = class),
grid = 7,
seed = 42,
verbose = TRUE,
control = control_resamples(save_pred = TRUE))i 1 of 2 tuning: rec1_xgb
i Creating pre-processing data to finalize unknown parameter: mtry
Warning: package 'stopwords' was built under R version 4.2.3
Warning: package 'SnowballC' was built under R version 4.2.3
Warning: package 'xgboost' was built under R version 4.2.3
✔ 1 of 2 tuning: rec1_xgb (1m 22.2s)
i 2 of 2 tuning: rec2_xgb
i Creating pre-processing data to finalize unknown parameter: mtry
✔ 2 of 2 tuning: rec2_xgb (1m 48s)
1.4.1.4 Ergebnisse
tune::autoplot(model_set) +
theme(legend.position = "bottom")
model_set %>%
collect_metrics() %>%
arrange(-mean)Rezept Zwei hat besser abgeschnitten als Rezept Eins. Wählen wir nun das beste Modell aus und fitten es:
1.4.1.5 Finalisieren
best_model_params <-
extract_workflow_set_result(model_set, "rec2_xgb") %>%
select_best()Warning: No value of `metric` was given; metric 'roc_auc' will be used.
best_wf <-
all_workflows %>%
extract_workflow("rec2_xgb")
best_wf_finalized <-
best_wf %>%
finalize_workflow(best_model_params)
fit_final <- fit(best_wf_finalized, data = d_train)fit_final %>%
extract_fit_parsnip() %>%
vip()
Die Analyse der wichtigsten Prädiktoren deckt sich mit den Erkenntnissen aus der EDA. Die mit Abstand wichtigsten Features sind die Beleidigungen und Sentimentwerte, während die Tf-idf-Maße von Beleidigungen ebenfalls viel zur Prediction beitragen.
wf_preds <-
collect_predictions(model_set)
wf_preds %>%
group_by(wflow_id) %>%
roc_curve(truth = class, `.pred_hate speech`) %>%
autoplot()
Die Performance im Train-Sample fällt sehr gut aus, da die Vorhersagen mit einer Genauigkeit von rund 90 Prozent sehr präzise sind.
1.4.1.6 Vorhersagen
preds <- predict(fit_final, d_test)
preds1.4.1.7 Bestimmen der Vorhersagegüte im Test-Sample
d_test1 <-
d_test %>%
bind_cols(preds) %>%
mutate(class = as.factor(class))
d_test1my_metrics <- metric_set(accuracy, f_meas)
my_metrics(d_test1,
truth = class,
estimate = .pred_class)Auch im Test-Sample bewährt sich das Modell mit einer sehr hohen Genauigkeit.
1.4.2 Klassifikation mit Transformer
Ein weiterer Ansatz zur Klassifikation von Hate Speech ist es, kein eigenes Modell zu trainieren, sondern Zero-Shot-Learning anzuwenden. Das ergibt natürlich am meisten Sinn mit einem sehr fortgeschrittenen und komplexen Transformer-Modell, das bereits auf die Erkennung von Hate Speech trainiert wurde. Im Folgenden wird daher das Modell roberta-hate-speech-dynabench-r4-target von Facebook, welches auf Huggingface.co verfügbar ist, um die Tweets nach Hate Speech zu klassifizieren. Hierzu wird der Befehl pipeline aus der transformers-Library von Huggingface genutzt, um das Modell zu laden und auf das Test-Sample anzuwenden.
library(reticulate)Warning: package 'reticulate' was built under R version 4.2.3
use_virtualenv("C:/Users/rapha/venv")from transformers import pipelineimport tensorflow as tfclassifier = pipeline("text-classification", model="facebook/roberta-hate-speech-dynabench-r4-target")WARNING:tensorflow:From C:\Users\rapha\venv\Lib\site-packages\keras\src\backend.py:873: The name tf.get_default_graph is deprecated. Please use tf.compat.v1.get_default_graph instead.
Some weights of the PyTorch model were not used when initializing the TF 2.0 model TFRobertaForSequenceClassification: ['roberta.embeddings.position_ids']
- This IS expected if you are initializing TFRobertaForSequenceClassification from a PyTorch model trained on another task or with another architecture (e.g. initializing a TFBertForSequenceClassification model from a BertForPreTraining model).
- This IS NOT expected if you are initializing TFRobertaForSequenceClassification from a PyTorch model that you expect to be exactly identical (e.g. initializing a TFBertForSequenceClassification model from a BertForSequenceClassification model).
All the weights of TFRobertaForSequenceClassification were initialized from the PyTorch model.
If your task is similar to the task the model of the checkpoint was trained on, you can already use TFRobertaForSequenceClassification for predictions without further training.
tweets <- d_test$tweettweets = r.tweets
results = classifier(tweets)result <- py$results
labels <- lapply(result, function(element) element$label)
tweets_hate <- cbind(d_test, pred = unlist(labels))
tweets_hate <- tweets_hate %>%
mutate(class = as.factor(class),
pred = case_when(pred == "hate" ~ "hate speech",
pred == "nothate" ~ "other"),
pred = as.factor(pred))my_metrics2 <- metric_set(accuracy, f_meas)
my_metrics2(tweets_hate,
truth = class,
estimate = pred)Die Performance des Modells ist objektiv gesehen gut, verglichen mit dem XGBoost mit einer Minute Trainingszeit fällt sie jedoch mager aus.
1.4.3 Neuronales Netzwerk
Bisher wurde Hate Speech sowohl mit Hilfe eines auf den konkreten Daten trainierten Shallow-Learner als auch mit Hilfe eines vortrainierten Transformers klassifiziert. Im letzten Schritt dieses Posts sollen die Stärken dieser beiden Ansätze kombiniert werden, indem ein Deep-Learning-Algorithums, genauer gesagt ein Neuronales Netzwerk, auf den vorliegenden Daten trainiert wird. Das neuronale Netz verwendet ein vortrainiertes Wort-Einbettungsmodell mit 50 Dimensionen, das für die deutsche Sprache optimiert ist. Dieses Embedding-Modell ermöglicht es dem Netzwerk, semantische Repräsentationen der Wörter zu erlernen. Das Netzwerk besteht aus einer Eingabeschicht, die das Embedding-Modell enthält, gefolgt von einer vollständig verbundenen Schicht mit 32 Neuronen und einer Sigmoid-Aktivierungsfunktion. Weiterhin gibt es eine Schicht mit 24 Neuronen und einer ReLU-Aktivierung. Die Ausgabeschicht besteht aus einem einzelnen Neuron für binäre Klassifikation. Das Netzwerk wird mit dem Adam-Optimizer kompiliert und die binäre Kreuzentropie wird als Verlustfunktion verwendet. Die Accuracy wird als Metrik überwacht. Das Training erfolgt über 3 Epochen mit einer Batch-Größe von 48, wobei die Validierung anhand des Test-Samples durchgeführt wird.
import pandas as pd
import numpy as np
import tensorflow_hub as hub
from tensorflow.keras.models import Sequential
from tensorflow.keras.layers import Dense
from sklearn.metrics import accuracy_score
from sklearn.model_selection import GridSearchCV
from sklearn.metrics import make_scorerd_train = r.d_train
d_test = r.d_test
X_train = d_train["tweet"].values
X_test = d_test["tweet"].valuesd_train["y"] = d_train["class"].map({"other" : 0, "hate speech" : 1})
y_train = d_train.loc[:, "y"].values
d_test["y"] = d_test["class"].map({"other" : 0, "hate speech" : 1})
y_test = d_test.loc[:, "y"].valuesembedding = "https://tfhub.dev/google/nnlm-de-dim50/2"
hub_layer = hub.KerasLayer(embedding, input_shape=[],
dtype=tf.string, trainable=True)tf.random.set_seed(42)model = tf.keras.Sequential()
model.add(hub_layer)
model.add(tf.keras.layers.Dense(32, activation='sigmoid'))
model.add(tf.keras.layers.Dense(24, activation='relu'))
model.add(tf.keras.layers.Dense(1))model.compile(optimizer='adam',
loss=tf.keras.losses.BinaryCrossentropy(from_logits=True),
metrics=['accuracy'])WARNING:tensorflow:From C:\Users\rapha\venv\Lib\site-packages\keras\src\optimizers\__init__.py:309: The name tf.train.Optimizer is deprecated. Please use tf.compat.v1.train.Optimizer instead.
WARNING:tensorflow:From C:\Users\rapha\venv\Lib\site-packages\keras\src\optimizers\__init__.py:309: The name tf.train.Optimizer is deprecated. Please use tf.compat.v1.train.Optimizer instead.
model.fit(X_train, y_train,
epochs=3,
batch_size=48,
validation_data=(X_test, y_test),
verbose = 1)Epoch 1/3
1/94 [..............................] - ETA: 5:29 - loss: 0.7612 - accuracy: 0.7500
2/94 [..............................] - ETA: 1:14 - loss: 0.7540 - accuracy: 0.7604
3/94 [..............................] - ETA: 1:15 - loss: 0.7420 - accuracy: 0.7500
4/94 [>.............................] - ETA: 58s - loss: 0.7310 - accuracy: 0.7240
5/94 [>.............................] - ETA: 49s - loss: 0.7212 - accuracy: 0.7333
6/94 [>.............................] - ETA: 43s - loss: 0.7104 - accuracy: 0.7604
7/94 [=>............................] - ETA: 39s - loss: 0.7030 - accuracy: 0.7560
8/94 [=>............................] - ETA: 36s - loss: 0.6960 - accuracy: 0.7578
9/94 [=>............................] - ETA: 34s - loss: 0.6861 - accuracy: 0.7639
10/94 [==>...........................] - ETA: 32s - loss: 0.6813 - accuracy: 0.7583
11/94 [==>...........................] - ETA: 31s - loss: 0.6698 - accuracy: 0.7689
12/94 [==>...........................] - ETA: 29s - loss: 0.6638 - accuracy: 0.7674
13/94 [===>..........................] - ETA: 28s - loss: 0.6575 - accuracy: 0.7676
14/94 [===>..........................] - ETA: 27s - loss: 0.6523 - accuracy: 0.7664
15/94 [===>..........................] - ETA: 26s - loss: 0.6486 - accuracy: 0.7625
16/94 [====>.........................] - ETA: 25s - loss: 0.6449 - accuracy: 0.7604
17/94 [====>.........................] - ETA: 25s - loss: 0.6424 - accuracy: 0.7574
18/94 [====>.........................] - ETA: 24s - loss: 0.6411 - accuracy: 0.7535
19/94 [=====>........................] - ETA: 23s - loss: 0.6422 - accuracy: 0.7478
20/94 [=====>........................] - ETA: 23s - loss: 0.6401 - accuracy: 0.7458
21/94 [=====>........................] - ETA: 22s - loss: 0.6346 - accuracy: 0.7480
22/94 [======>.......................] - ETA: 21s - loss: 0.6309 - accuracy: 0.7481
23/94 [======>.......................] - ETA: 21s - loss: 0.6251 - accuracy: 0.7509
24/94 [======>.......................] - ETA: 20s - loss: 0.6251 - accuracy: 0.7483
25/94 [======>.......................] - ETA: 20s - loss: 0.6224 - accuracy: 0.7483
26/94 [=======>......................] - ETA: 19s - loss: 0.6266 - accuracy: 0.7420
27/94 [=======>......................] - ETA: 19s - loss: 0.6284 - accuracy: 0.7377
28/94 [=======>......................] - ETA: 19s - loss: 0.6252 - accuracy: 0.7388
29/94 [========>.....................] - ETA: 18s - loss: 0.6284 - accuracy: 0.7342
30/94 [========>.....................] - ETA: 18s - loss: 0.6231 - accuracy: 0.7375
31/94 [========>.....................] - ETA: 17s - loss: 0.6187 - accuracy: 0.7399
32/94 [=========>....................] - ETA: 17s - loss: 0.6161 - accuracy: 0.7409
33/94 [=========>....................] - ETA: 17s - loss: 0.6127 - accuracy: 0.7424
34/94 [=========>....................] - ETA: 16s - loss: 0.6138 - accuracy: 0.7402
35/94 [==========>...................] - ETA: 16s - loss: 0.6112 - accuracy: 0.7417
36/94 [==========>...................] - ETA: 16s - loss: 0.6092 - accuracy: 0.7425
37/94 [==========>...................] - ETA: 15s - loss: 0.6086 - accuracy: 0.7421
38/94 [===========>..................] - ETA: 15s - loss: 0.6048 - accuracy: 0.7445
39/94 [===========>..................] - ETA: 15s - loss: 0.6033 - accuracy: 0.7447
40/94 [===========>..................] - ETA: 14s - loss: 0.6008 - accuracy: 0.7458
41/94 [============>.................] - ETA: 14s - loss: 0.5989 - accuracy: 0.7464
42/94 [============>.................] - ETA: 14s - loss: 0.5956 - accuracy: 0.7485
43/94 [============>.................] - ETA: 13s - loss: 0.5973 - accuracy: 0.7461
44/94 [=============>................] - ETA: 13s - loss: 0.5969 - accuracy: 0.7457
45/94 [=============>................] - ETA: 13s - loss: 0.5967 - accuracy: 0.7449
46/94 [=============>................] - ETA: 12s - loss: 0.5959 - accuracy: 0.7450
47/94 [==============>...............] - ETA: 12s - loss: 0.5935 - accuracy: 0.7465
48/94 [==============>...............] - ETA: 12s - loss: 0.5920 - accuracy: 0.7470
49/94 [==============>...............] - ETA: 11s - loss: 0.5928 - accuracy: 0.7457
50/94 [==============>...............] - ETA: 11s - loss: 0.5921 - accuracy: 0.7458
51/94 [===============>..............] - ETA: 11s - loss: 0.5909 - accuracy: 0.7463
52/94 [===============>..............] - ETA: 11s - loss: 0.5897 - accuracy: 0.7468
53/94 [===============>..............] - ETA: 10s - loss: 0.5883 - accuracy: 0.7472
54/94 [================>.............] - ETA: 10s - loss: 0.5886 - accuracy: 0.7465
55/94 [================>.............] - ETA: 10s - loss: 0.5909 - accuracy: 0.7439
56/94 [================>.............] - ETA: 9s - loss: 0.5918 - accuracy: 0.7426
57/94 [=================>............] - ETA: 9s - loss: 0.5894 - accuracy: 0.7442
58/94 [=================>............] - ETA: 9s - loss: 0.5880 - accuracy: 0.7450
59/94 [=================>............] - ETA: 9s - loss: 0.5873 - accuracy: 0.7451
60/94 [==================>...........] - ETA: 8s - loss: 0.5867 - accuracy: 0.7451
61/94 [==================>...........] - ETA: 8s - loss: 0.5855 - accuracy: 0.7459
62/94 [==================>...........] - ETA: 8s - loss: 0.5840 - accuracy: 0.7466
63/94 [===================>..........] - ETA: 7s - loss: 0.5853 - accuracy: 0.7450
64/94 [===================>..........] - ETA: 7s - loss: 0.5857 - accuracy: 0.7441
65/94 [===================>..........] - ETA: 7s - loss: 0.5856 - accuracy: 0.7439
66/94 [====================>.........] - ETA: 7s - loss: 0.5852 - accuracy: 0.7440
67/94 [====================>.........] - ETA: 6s - loss: 0.5848 - accuracy: 0.7438
68/94 [====================>.........] - ETA: 6s - loss: 0.5842 - accuracy: 0.7439
69/94 [=====================>........] - ETA: 6s - loss: 0.5838 - accuracy: 0.7440
70/94 [=====================>........] - ETA: 6s - loss: 0.5837 - accuracy: 0.7435
71/94 [=====================>........] - ETA: 5s - loss: 0.5833 - accuracy: 0.7433
72/94 [=====================>........] - ETA: 5s - loss: 0.5842 - accuracy: 0.7419
73/94 [======================>.......] - ETA: 5s - loss: 0.5834 - accuracy: 0.7423
74/94 [======================>.......] - ETA: 5s - loss: 0.5829 - accuracy: 0.7424
75/94 [======================>.......] - ETA: 4s - loss: 0.5832 - accuracy: 0.7417
76/94 [=======================>......] - ETA: 4s - loss: 0.5841 - accuracy: 0.7404
77/94 [=======================>......] - ETA: 4s - loss: 0.5843 - accuracy: 0.7397
78/94 [=======================>......] - ETA: 4s - loss: 0.5845 - accuracy: 0.7390
79/94 [========================>.....] - ETA: 3s - loss: 0.5839 - accuracy: 0.7392
80/94 [========================>.....] - ETA: 3s - loss: 0.5832 - accuracy: 0.7396
81/94 [========================>.....] - ETA: 3s - loss: 0.5817 - accuracy: 0.7410
82/94 [=========================>....] - ETA: 3s - loss: 0.5816 - accuracy: 0.7406
83/94 [=========================>....] - ETA: 2s - loss: 0.5810 - accuracy: 0.7407
84/94 [=========================>....] - ETA: 2s - loss: 0.5805 - accuracy: 0.7408
85/94 [==========================>...] - ETA: 2s - loss: 0.5796 - accuracy: 0.7414
86/94 [==========================>...] - ETA: 1s - loss: 0.5784 - accuracy: 0.7422
87/94 [==========================>...] - ETA: 1s - loss: 0.5786 - accuracy: 0.7416
88/94 [===========================>..] - ETA: 1s - loss: 0.5788 - accuracy: 0.7410
89/94 [===========================>..] - ETA: 1s - loss: 0.5775 - accuracy: 0.7420
90/94 [===========================>..] - ETA: 0s - loss: 0.5759 - accuracy: 0.7433
91/94 [============================>.] - ETA: 0s - loss: 0.5744 - accuracy: 0.7443
92/94 [============================>.] - ETA: 0s - loss: 0.5749 - accuracy: 0.7434
93/94 [============================>.] - ETA: 0s - loss: 0.5741 - accuracy: 0.7440
94/94 [==============================] - ETA: 0s - loss: 0.5736 - accuracy: 0.7443
94/94 [==============================] - 28s 265ms/step - loss: 0.5736 - accuracy: 0.7443 - val_loss: 0.5384 - val_accuracy: 0.7444
Epoch 2/3
1/94 [..............................] - ETA: 20s - loss: 0.6250 - accuracy: 0.6458
2/94 [..............................] - ETA: 21s - loss: 0.5874 - accuracy: 0.6875
3/94 [..............................] - ETA: 20s - loss: 0.5864 - accuracy: 0.6944
4/94 [>.............................] - ETA: 20s - loss: 0.5723 - accuracy: 0.7083
5/94 [>.............................] - ETA: 20s - loss: 0.5645 - accuracy: 0.7125
6/94 [>.............................] - ETA: 19s - loss: 0.5472 - accuracy: 0.7257
7/94 [=>............................] - ETA: 19s - loss: 0.5401 - accuracy: 0.7321
8/94 [=>............................] - ETA: 19s - loss: 0.5425 - accuracy: 0.7292
9/94 [=>............................] - ETA: 19s - loss: 0.5537 - accuracy: 0.7199
10/94 [==>...........................] - ETA: 19s - loss: 0.5499 - accuracy: 0.7229
11/94 [==>...........................] - ETA: 18s - loss: 0.5413 - accuracy: 0.7311
12/94 [==>...........................] - ETA: 18s - loss: 0.5350 - accuracy: 0.7361
13/94 [===>..........................] - ETA: 18s - loss: 0.5427 - accuracy: 0.7292
14/94 [===>..........................] - ETA: 18s - loss: 0.5492 - accuracy: 0.7217
15/94 [===>..........................] - ETA: 17s - loss: 0.5397 - accuracy: 0.7306
16/94 [====>.........................] - ETA: 17s - loss: 0.5339 - accuracy: 0.7357
17/94 [====>.........................] - ETA: 17s - loss: 0.5271 - accuracy: 0.7426
18/94 [====>.........................] - ETA: 17s - loss: 0.5285 - accuracy: 0.7407
19/94 [=====>........................] - ETA: 16s - loss: 0.5347 - accuracy: 0.7346
20/94 [=====>........................] - ETA: 16s - loss: 0.5373 - accuracy: 0.7323
21/94 [=====>........................] - ETA: 16s - loss: 0.5342 - accuracy: 0.7341
22/94 [======>.......................] - ETA: 16s - loss: 0.5313 - accuracy: 0.7367
23/94 [======>.......................] - ETA: 16s - loss: 0.5267 - accuracy: 0.7400
24/94 [======>.......................] - ETA: 15s - loss: 0.5270 - accuracy: 0.7396
25/94 [======>.......................] - ETA: 15s - loss: 0.5225 - accuracy: 0.7433
26/94 [=======>......................] - ETA: 15s - loss: 0.5173 - accuracy: 0.7484
27/94 [=======>......................] - ETA: 15s - loss: 0.5167 - accuracy: 0.7485
28/94 [=======>......................] - ETA: 14s - loss: 0.5173 - accuracy: 0.7470
29/94 [========>.....................] - ETA: 14s - loss: 0.5180 - accuracy: 0.7457
30/94 [========>.....................] - ETA: 14s - loss: 0.5179 - accuracy: 0.7451
31/94 [========>.....................] - ETA: 14s - loss: 0.5167 - accuracy: 0.7460
32/94 [=========>....................] - ETA: 14s - loss: 0.5158 - accuracy: 0.7461
33/94 [=========>....................] - ETA: 13s - loss: 0.5171 - accuracy: 0.7443
34/94 [=========>....................] - ETA: 13s - loss: 0.5174 - accuracy: 0.7439
35/94 [==========>...................] - ETA: 13s - loss: 0.5161 - accuracy: 0.7440
36/94 [==========>...................] - ETA: 13s - loss: 0.5150 - accuracy: 0.7448
37/94 [==========>...................] - ETA: 12s - loss: 0.5109 - accuracy: 0.7483
38/94 [===========>..................] - ETA: 12s - loss: 0.5112 - accuracy: 0.7473
39/94 [===========>..................] - ETA: 12s - loss: 0.5105 - accuracy: 0.7468
40/94 [===========>..................] - ETA: 12s - loss: 0.5101 - accuracy: 0.7469
41/94 [============>.................] - ETA: 11s - loss: 0.5098 - accuracy: 0.7464
42/94 [============>.................] - ETA: 11s - loss: 0.5097 - accuracy: 0.7460
43/94 [============>.................] - ETA: 11s - loss: 0.5093 - accuracy: 0.7452
44/94 [=============>................] - ETA: 11s - loss: 0.5086 - accuracy: 0.7453
45/94 [=============>................] - ETA: 11s - loss: 0.5072 - accuracy: 0.7458
46/94 [=============>................] - ETA: 10s - loss: 0.5082 - accuracy: 0.7437
47/94 [==============>...............] - ETA: 10s - loss: 0.5065 - accuracy: 0.7438
48/94 [==============>...............] - ETA: 10s - loss: 0.5055 - accuracy: 0.7444
49/94 [==============>...............] - ETA: 10s - loss: 0.5044 - accuracy: 0.7445
50/94 [==============>...............] - ETA: 9s - loss: 0.5048 - accuracy: 0.7437
51/94 [===============>..............] - ETA: 9s - loss: 0.5057 - accuracy: 0.7422
52/94 [===============>..............] - ETA: 9s - loss: 0.5035 - accuracy: 0.7436
53/94 [===============>..............] - ETA: 9s - loss: 0.5037 - accuracy: 0.7429
54/94 [================>.............] - ETA: 9s - loss: 0.5032 - accuracy: 0.7427
55/94 [================>.............] - ETA: 8s - loss: 0.5009 - accuracy: 0.7443
56/94 [================>.............] - ETA: 8s - loss: 0.5013 - accuracy: 0.7422
57/94 [=================>............] - ETA: 8s - loss: 0.5008 - accuracy: 0.7423
58/94 [=================>............] - ETA: 8s - loss: 0.4997 - accuracy: 0.7428
59/94 [=================>............] - ETA: 7s - loss: 0.4983 - accuracy: 0.7436
60/94 [==================>...........] - ETA: 7s - loss: 0.4981 - accuracy: 0.7431
61/94 [==================>...........] - ETA: 7s - loss: 0.4974 - accuracy: 0.7435
62/94 [==================>...........] - ETA: 7s - loss: 0.4964 - accuracy: 0.7436
63/94 [===================>..........] - ETA: 6s - loss: 0.4965 - accuracy: 0.7417
64/94 [===================>..........] - ETA: 6s - loss: 0.4957 - accuracy: 0.7419
65/94 [===================>..........] - ETA: 6s - loss: 0.4942 - accuracy: 0.7429
66/94 [====================>.........] - ETA: 6s - loss: 0.4932 - accuracy: 0.7427
67/94 [====================>.........] - ETA: 6s - loss: 0.4915 - accuracy: 0.7441
68/94 [====================>.........] - ETA: 5s - loss: 0.4910 - accuracy: 0.7430
69/94 [=====================>........] - ETA: 5s - loss: 0.4919 - accuracy: 0.7406
70/94 [=====================>........] - ETA: 5s - loss: 0.4909 - accuracy: 0.7411
71/94 [=====================>........] - ETA: 5s - loss: 0.4882 - accuracy: 0.7430
72/94 [=====================>........] - ETA: 4s - loss: 0.4880 - accuracy: 0.7425
73/94 [======================>.......] - ETA: 4s - loss: 0.4863 - accuracy: 0.7437
74/94 [======================>.......] - ETA: 4s - loss: 0.4869 - accuracy: 0.7424
75/94 [======================>.......] - ETA: 4s - loss: 0.4850 - accuracy: 0.7439
76/94 [=======================>......] - ETA: 4s - loss: 0.4830 - accuracy: 0.7456
77/94 [=======================>......] - ETA: 3s - loss: 0.4822 - accuracy: 0.7459
78/94 [=======================>......] - ETA: 3s - loss: 0.4816 - accuracy: 0.7457
79/94 [========================>.....] - ETA: 3s - loss: 0.4816 - accuracy: 0.7447
80/94 [========================>.....] - ETA: 3s - loss: 0.4811 - accuracy: 0.7443
81/94 [========================>.....] - ETA: 2s - loss: 0.4810 - accuracy: 0.7441
82/94 [=========================>....] - ETA: 2s - loss: 0.4790 - accuracy: 0.7457
83/94 [=========================>....] - ETA: 2s - loss: 0.4779 - accuracy: 0.7467
84/94 [=========================>....] - ETA: 2s - loss: 0.4776 - accuracy: 0.7460
85/94 [==========================>...] - ETA: 2s - loss: 0.4771 - accuracy: 0.7456
86/94 [==========================>...] - ETA: 1s - loss: 0.4753 - accuracy: 0.7459
87/94 [==========================>...] - ETA: 1s - loss: 0.4754 - accuracy: 0.7455
88/94 [===========================>..] - ETA: 1s - loss: 0.4744 - accuracy: 0.7453
89/94 [===========================>..] - ETA: 1s - loss: 0.4728 - accuracy: 0.7458
90/94 [===========================>..] - ETA: 0s - loss: 0.4722 - accuracy: 0.7454
91/94 [============================>.] - ETA: 0s - loss: 0.4721 - accuracy: 0.7452
92/94 [============================>.] - ETA: 0s - loss: 0.4716 - accuracy: 0.7448
93/94 [============================>.] - ETA: 0s - loss: 0.4700 - accuracy: 0.7457
94/94 [==============================] - ETA: 0s - loss: 0.4696 - accuracy: 0.7461
94/94 [==============================] - 22s 231ms/step - loss: 0.4696 - accuracy: 0.7461 - val_loss: 0.4078 - val_accuracy: 0.7694
Epoch 3/3
1/94 [..............................] - ETA: 20s - loss: 0.3267 - accuracy: 0.8542
2/94 [..............................] - ETA: 20s - loss: 0.3459 - accuracy: 0.8229
3/94 [..............................] - ETA: 21s - loss: 0.3373 - accuracy: 0.8125
4/94 [>.............................] - ETA: 21s - loss: 0.3315 - accuracy: 0.8073
5/94 [>.............................] - ETA: 21s - loss: 0.3337 - accuracy: 0.7958
6/94 [>.............................] - ETA: 21s - loss: 0.3475 - accuracy: 0.7917
7/94 [=>............................] - ETA: 20s - loss: 0.3404 - accuracy: 0.8006
8/94 [=>............................] - ETA: 20s - loss: 0.3466 - accuracy: 0.7943
9/94 [=>............................] - ETA: 20s - loss: 0.3442 - accuracy: 0.8032
10/94 [==>...........................] - ETA: 20s - loss: 0.3392 - accuracy: 0.8083
11/94 [==>...........................] - ETA: 19s - loss: 0.3358 - accuracy: 0.8068
12/94 [==>...........................] - ETA: 19s - loss: 0.3321 - accuracy: 0.8090
13/94 [===>..........................] - ETA: 19s - loss: 0.3294 - accuracy: 0.8141
14/94 [===>..........................] - ETA: 19s - loss: 0.3287 - accuracy: 0.8155
15/94 [===>..........................] - ETA: 18s - loss: 0.3260 - accuracy: 0.8194
16/94 [====>.........................] - ETA: 18s - loss: 0.3209 - accuracy: 0.8242
17/94 [====>.........................] - ETA: 18s - loss: 0.3193 - accuracy: 0.8284
18/94 [====>.........................] - ETA: 18s - loss: 0.3199 - accuracy: 0.8264
19/94 [=====>........................] - ETA: 18s - loss: 0.3217 - accuracy: 0.8224
20/94 [=====>........................] - ETA: 17s - loss: 0.3201 - accuracy: 0.8260
21/94 [=====>........................] - ETA: 17s - loss: 0.3176 - accuracy: 0.8264
22/94 [======>.......................] - ETA: 17s - loss: 0.3133 - accuracy: 0.8295
23/94 [======>.......................] - ETA: 17s - loss: 0.3119 - accuracy: 0.8288
24/94 [======>.......................] - ETA: 17s - loss: 0.3090 - accuracy: 0.8307
25/94 [======>.......................] - ETA: 16s - loss: 0.3111 - accuracy: 0.8292
26/94 [=======>......................] - ETA: 16s - loss: 0.3098 - accuracy: 0.8301
27/94 [=======>......................] - ETA: 16s - loss: 0.3088 - accuracy: 0.8302
28/94 [=======>......................] - ETA: 15s - loss: 0.3106 - accuracy: 0.8274
29/94 [========>.....................] - ETA: 15s - loss: 0.3073 - accuracy: 0.8312
30/94 [========>.....................] - ETA: 15s - loss: 0.3091 - accuracy: 0.8285
31/94 [========>.....................] - ETA: 15s - loss: 0.3089 - accuracy: 0.8293
32/94 [=========>....................] - ETA: 15s - loss: 0.3050 - accuracy: 0.8327
33/94 [=========>....................] - ETA: 14s - loss: 0.3034 - accuracy: 0.8352
34/94 [=========>....................] - ETA: 14s - loss: 0.3024 - accuracy: 0.8370
35/94 [==========>...................] - ETA: 14s - loss: 0.3010 - accuracy: 0.8387
36/94 [==========>...................] - ETA: 14s - loss: 0.2993 - accuracy: 0.8409
37/94 [==========>...................] - ETA: 13s - loss: 0.2973 - accuracy: 0.8435
38/94 [===========>..................] - ETA: 13s - loss: 0.2974 - accuracy: 0.8432
39/94 [===========>..................] - ETA: 13s - loss: 0.2952 - accuracy: 0.8456
40/94 [===========>..................] - ETA: 13s - loss: 0.2947 - accuracy: 0.8458
41/94 [============>.................] - ETA: 12s - loss: 0.2944 - accuracy: 0.8455
42/94 [============>.................] - ETA: 12s - loss: 0.2937 - accuracy: 0.8452
43/94 [============>.................] - ETA: 12s - loss: 0.2943 - accuracy: 0.8450
44/94 [=============>................] - ETA: 12s - loss: 0.2951 - accuracy: 0.8452
45/94 [=============>................] - ETA: 11s - loss: 0.2943 - accuracy: 0.8463
46/94 [=============>................] - ETA: 11s - loss: 0.2928 - accuracy: 0.8474
47/94 [==============>...............] - ETA: 11s - loss: 0.2914 - accuracy: 0.8484
48/94 [==============>...............] - ETA: 11s - loss: 0.2905 - accuracy: 0.8490
49/94 [==============>...............] - ETA: 10s - loss: 0.2901 - accuracy: 0.8491
50/94 [==============>...............] - ETA: 10s - loss: 0.2906 - accuracy: 0.8487
51/94 [===============>..............] - ETA: 10s - loss: 0.2894 - accuracy: 0.8497
52/94 [===============>..............] - ETA: 10s - loss: 0.2894 - accuracy: 0.8490
53/94 [===============>..............] - ETA: 9s - loss: 0.2883 - accuracy: 0.8510
54/94 [================>.............] - ETA: 9s - loss: 0.2859 - accuracy: 0.8534
55/94 [================>.............] - ETA: 9s - loss: 0.2850 - accuracy: 0.8534
56/94 [================>.............] - ETA: 9s - loss: 0.2851 - accuracy: 0.8542
57/94 [=================>............] - ETA: 8s - loss: 0.2863 - accuracy: 0.8531
58/94 [=================>............] - ETA: 8s - loss: 0.2845 - accuracy: 0.8542
59/94 [=================>............] - ETA: 8s - loss: 0.2837 - accuracy: 0.8552
60/94 [==================>...........] - ETA: 8s - loss: 0.2823 - accuracy: 0.8566
61/94 [==================>...........] - ETA: 7s - loss: 0.2815 - accuracy: 0.8572
62/94 [==================>...........] - ETA: 7s - loss: 0.2806 - accuracy: 0.8575
63/94 [===================>..........] - ETA: 7s - loss: 0.2802 - accuracy: 0.8575
64/94 [===================>..........] - ETA: 7s - loss: 0.2785 - accuracy: 0.8594
65/94 [===================>..........] - ETA: 7s - loss: 0.2770 - accuracy: 0.8609
66/94 [====================>.........] - ETA: 6s - loss: 0.2754 - accuracy: 0.8621
67/94 [====================>.........] - ETA: 6s - loss: 0.2755 - accuracy: 0.8626
68/94 [====================>.........] - ETA: 6s - loss: 0.2736 - accuracy: 0.8640
69/94 [=====================>........] - ETA: 6s - loss: 0.2742 - accuracy: 0.8638
70/94 [=====================>........] - ETA: 5s - loss: 0.2721 - accuracy: 0.8649
71/94 [=====================>........] - ETA: 5s - loss: 0.2706 - accuracy: 0.8656
72/94 [=====================>........] - ETA: 5s - loss: 0.2695 - accuracy: 0.8663
73/94 [======================>.......] - ETA: 5s - loss: 0.2688 - accuracy: 0.8667
74/94 [======================>.......] - ETA: 4s - loss: 0.2681 - accuracy: 0.8671
75/94 [======================>.......] - ETA: 4s - loss: 0.2670 - accuracy: 0.8678
76/94 [=======================>......] - ETA: 4s - loss: 0.2645 - accuracy: 0.8695
77/94 [=======================>......] - ETA: 4s - loss: 0.2626 - accuracy: 0.8704
78/94 [=======================>......] - ETA: 3s - loss: 0.2615 - accuracy: 0.8713
79/94 [========================>.....] - ETA: 3s - loss: 0.2607 - accuracy: 0.8716
80/94 [========================>.....] - ETA: 3s - loss: 0.2599 - accuracy: 0.8724
81/94 [========================>.....] - ETA: 3s - loss: 0.2595 - accuracy: 0.8729
82/94 [=========================>....] - ETA: 2s - loss: 0.2587 - accuracy: 0.8735
83/94 [=========================>....] - ETA: 2s - loss: 0.2587 - accuracy: 0.8740
84/94 [=========================>....] - ETA: 2s - loss: 0.2573 - accuracy: 0.8750
85/94 [==========================>...] - ETA: 2s - loss: 0.2559 - accuracy: 0.8755
86/94 [==========================>...] - ETA: 1s - loss: 0.2546 - accuracy: 0.8762
87/94 [==========================>...] - ETA: 1s - loss: 0.2532 - accuracy: 0.8769
88/94 [===========================>..] - ETA: 1s - loss: 0.2523 - accuracy: 0.8774
89/94 [===========================>..] - ETA: 1s - loss: 0.2521 - accuracy: 0.8776
90/94 [===========================>..] - ETA: 0s - loss: 0.2519 - accuracy: 0.8775
91/94 [============================>.] - ETA: 0s - loss: 0.2504 - accuracy: 0.8787
92/94 [============================>.] - ETA: 0s - loss: 0.2505 - accuracy: 0.8788
93/94 [============================>.] - ETA: 0s - loss: 0.2498 - accuracy: 0.8795
94/94 [==============================] - ETA: 0s - loss: 0.2498 - accuracy: 0.8795
94/94 [==============================] - 23s 242ms/step - loss: 0.2498 - accuracy: 0.8795 - val_loss: 0.2964 - val_accuracy: 0.8785
<keras.src.callbacks.History object at 0x0000017233C43750>
WARNING:tensorflow:From C:\Users\rapha\venv\Lib\site-packages\keras\src\utils\tf_utils.py:492: The name tf.ragged.RaggedTensorValue is deprecated. Please use tf.compat.v1.ragged.RaggedTensorValue instead.
WARNING:tensorflow:From C:\Users\rapha\venv\Lib\site-packages\keras\src\utils\tf_utils.py:492: The name tf.ragged.RaggedTensorValue is deprecated. Please use tf.compat.v1.ragged.RaggedTensorValue instead.
WARNING:tensorflow:From C:\Users\rapha\venv\Lib\site-packages\keras\src\engine\base_layer_utils.py:384: The name tf.executing_eagerly_outside_functions is deprecated. Please use tf.compat.v1.executing_eagerly_outside_functions instead.
WARNING:tensorflow:From C:\Users\rapha\venv\Lib\site-packages\keras\src\engine\base_layer_utils.py:384: The name tf.executing_eagerly_outside_functions is deprecated. Please use tf.compat.v1.executing_eagerly_outside_functions instead.
y_pred_probs = model.predict(X_test)
1/35 [..............................] - ETA: 5s
4/35 [==>...........................] - ETA: 0s
8/35 [=====>........................] - ETA: 0s
12/35 [=========>....................] - ETA: 0s
16/35 [============>.................] - ETA: 0s
19/35 [===============>..............] - ETA: 0s
23/35 [==================>...........] - ETA: 0s
26/35 [=====================>........] - ETA: 0s
29/35 [=======================>......] - ETA: 0s
32/35 [==========================>...] - ETA: 0s
35/35 [==============================] - 1s 18ms/step
y_pred = (model.predict(X_test) > 0.5).astype("int32")
1/35 [..............................] - ETA: 1s
4/35 [==>...........................] - ETA: 0s
7/35 [=====>........................] - ETA: 0s
11/35 [========>.....................] - ETA: 0s
15/35 [===========>..................] - ETA: 0s
18/35 [==============>...............] - ETA: 0s
21/35 [=================>............] - ETA: 0s
24/35 [===================>..........] - ETA: 0s
27/35 [======================>.......] - ETA: 0s
31/35 [=========================>....] - ETA: 0s
34/35 [============================>.] - ETA: 0s
35/35 [==============================] - 1s 18ms/step
accuracy = accuracy_score(y_test, y_pred)
print(f"Test Accuracy: {accuracy}")Test Accuracy: 0.8784629133154602
from sklearn.metrics import confusion_matrix
conf_matrix = confusion_matrix(y_test, y_pred)
print("Confusion Matrix:")Confusion Matrix:
print(conf_matrix)[[817 16]
[120 166]]
Das neuronale Netzwerk sagt das Train-Sample zwar perfekt vorher, hat jedoch vergleichsweise große Schwierigkeiten beim Test-Sample.
1.5 Fazit
Durch die explorative Datenanalyse war es möglich, einige relevante Charakteristika herauszuarbeiten, die Hate-Speech-Tweets klar von anderen Tweets abgrenzen. Hate Speech enthält nämlich einen großen Anteil an Beleidigungen und Schimpfwörtern sowie negativen Sentimenten. Diese Erkenntnisse waren für die Modellierung hilfreich, da es gelang, Features basierend auf der EDA zu generieren, die von hoher Relevanz für die Performance des Modells waren. Das Ziel der Modellierung war es, ein Modell zu trainieren, das Hate Speech in Tweets möglichst akkurat erkennt. Durch den kombinierten Ansatz aus Training und Deep Learning wurde dieses Ziel mit Erfolg erreicht, auch wenn die Deep Learning Modelle vergleichsweise schlecht abschnitten.